4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
11 // You must not remove this notice, or any other, from this software.
16 namespace Microsoft
.JScript
{
19 using System
.Collections
;
20 using System
.Reflection
;
21 using System
.Reflection
.Emit
;
23 internal sealed class For
: AST
{
24 private AST initializer
;
25 private AST condition
;
26 private AST incrementer
;
28 private Completion completion
;
30 internal For(Context context
, AST initializer
, AST condition
, AST incrementer
, AST body
)
32 this.initializer
= initializer
;
33 this.condition
= condition
;
34 this.incrementer
= incrementer
;
36 this.completion
= new Completion();
39 // no debug info for the for statement iteself
40 internal override Object
Evaluate(){
41 this.completion
.Continue
= 0;
42 this.completion
.Exit
= 0;
43 this.completion
.value = null;
44 this.initializer
.Evaluate();
45 while (Convert
.ToBoolean(this.condition
.Evaluate()) == true){
46 Completion c
= (Completion
)this.body
.Evaluate();
48 this.completion
.value = c
.value;
50 this.completion
.Continue
= c
.Continue
- 1;
54 this.completion
.Exit
= c
.Exit
- 1;
59 this.incrementer
.Evaluate();
61 return this.completion
;
64 internal override AST
PartiallyEvaluate(){
65 this.initializer
= this.initializer
.PartiallyEvaluate();
66 ScriptObject current_scope
= Globals
.ScopeStack
.Peek();
67 while (current_scope
is WithObject
) current_scope
= current_scope
.GetParent();
68 if (current_scope
is FunctionScope
){
69 FunctionScope scope
= (FunctionScope
)current_scope
;
70 BitArray before
= scope
.DefinedFlags
;
71 this.condition
= this.condition
.PartiallyEvaluate();
72 //Do not need to clear the defined flags because the condition is always completely executed if the body is reached.
73 this.body
= this.body
.PartiallyEvaluate();
74 scope
.DefinedFlags
= before
;
75 this.incrementer
= this.incrementer
.PartiallyEvaluate();
76 scope
.DefinedFlags
= before
;
78 this.condition
= this.condition
.PartiallyEvaluate();
79 this.body
= this.body
.PartiallyEvaluate();
80 this.incrementer
= this.incrementer
.PartiallyEvaluate();
82 IReflect conditiontype
= this.condition
.InferType(null);
83 if (conditiontype
is FunctionPrototype
|| conditiontype
== Typeob
.ScriptFunction
)
84 this.context
.HandleError(JSError
.SuspectLoopCondition
);
88 internal override void TranslateToIL(ILGenerator il
, Type rtype
){
89 //This assumes that rtype == Void.class
90 Label body_start
= il
.DefineLabel();
91 Label continue_lab
= il
.DefineLabel();
92 Label first_time
= il
.DefineLabel();
93 Label loop_end
= il
.DefineLabel();
94 bool noCondition
= false;
95 compilerGlobals
.BreakLabelStack
.Push(loop_end
);
96 compilerGlobals
.ContinueLabelStack
.Push(continue_lab
);
97 if (!(this.initializer
is EmptyLiteral
)){
98 this.initializer
.context
.EmitLineInfo(il
);
99 this.initializer
.TranslateToIL(il
, Typeob
.Void
);
101 il
.MarkLabel(body_start
);
102 if (!(this.condition
is ConstantWrapper
) || !(this.condition
.Evaluate() is bool) || !((bool)this.condition
.Evaluate())){
103 this.condition
.context
.EmitLineInfo(il
);
104 this.condition
.TranslateToConditionalBranch(il
, false, loop_end
, false);
106 if (this.condition
.context
.StartPosition
+ 1 == this.condition
.context
.EndPosition
)
107 // the for does not have a condition specified. If there is no increment as well emit debug info for the whole for
109 this.body
.TranslateToIL(il
, Typeob
.Void
);
110 il
.MarkLabel(continue_lab
);
111 if (!(this.incrementer
is EmptyLiteral
)){
112 this.incrementer
.context
.EmitLineInfo(il
);
113 this.incrementer
.TranslateToIL(il
, Typeob
.Void
);
114 }else if (noCondition
){
115 this.context
.EmitLineInfo(il
);
117 il
.Emit(OpCodes
.Br
, body_start
);
118 il
.MarkLabel(loop_end
);
119 compilerGlobals
.BreakLabelStack
.Pop();
120 compilerGlobals
.ContinueLabelStack
.Pop();
123 internal override void TranslateToILInitializer(ILGenerator il
){
124 this.initializer
.TranslateToILInitializer(il
);
125 this.condition
.TranslateToILInitializer(il
);
126 this.incrementer
.TranslateToILInitializer(il
);
127 this.body
.TranslateToILInitializer(il
);